package com.goldcn.oss.service;

import com.aliyun.oss.OSSClient;
import com.aliyun.oss.model.OSSObject;
import com.goldcn.common.exception.ServiceException;
import com.goldcn.common.util.UuidUtils;
import com.goldcn.config.FileConfig;
import com.goldcn.config.OSSConfigure;
import com.goldcn.enumeration.ErrorCodeEnum;
import com.goldcn.file.service.UploadService;
import com.goldcn.file.util.CommonTools;
import com.goldcn.file.util.FileTypeJudge;
import com.goldcn.file.vo.FileVo;
import com.goldcn.oss.util.OSSManageUtil;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

/**
 * Created by Administrator on 2016/8/12.
 */
@Service
@Transactional
public class OssService {

    private Logger logger = Logger.getLogger(UploadService.class);

    @Autowired
    private OSSConfigure ossConfigure;

    @Autowired
    private FileConfig cfg;

    @Autowired
    private UploadService uploadService;


    /**
     * oss文件上传
     *
     * @param file
     * @return filevo 包含错误日志
     */
    @Transactional
    public FileVo uploadFiles(MultipartFile file) {
        FileVo vo = new FileVo();
        OSSClient ossClient = null;
        try {
            //验证文件类型
            this.verifyFileType(file.getInputStream());

            //验证文件大小
            this.verifyFileSize(file.getSize());

            ossClient = OSSManageUtil.getOSSClient(ossConfigure);
            String filename = OSSManageUtil.uploadFile(ossClient, ossConfigure.getBucketName(), file);

            vo.setFileName(filename);
            vo.setFileSize(file.getSize());
            vo.setFileUploadName(file.getOriginalFilename());
            return vo;
        } catch (ServiceException se) {
            vo.setErrorCode(se.getErrorCode());
            vo.setErrorDesc(se.getMessage());
        } catch (Exception e) {
            logger.info(e.getMessage());
            vo.setErrorDesc(ErrorCodeEnum.otherError.getErrorMsg());
            vo.setErrorCode(ErrorCodeEnum.otherError.getErrorCode());
        } finally {
            OSSManageUtil.closeOSSClient(ossClient);
        }
        return vo;
    }

    /**
     * oss文件上传
     *
     * @param base64Code
     * @param orientation
     * @return filevo 包含错误日志
     */
    @Transactional
    public FileVo uploadFiles(String base64Code, String orientation) {

        FileVo vo = new FileVo();
        OSSClient ossClient = null;
        try {

            File file = uploadService.saveBase64LoaclFolder(base64Code, orientation);

            ossClient = OSSManageUtil.getOSSClient(ossConfigure);
            String filename = OSSManageUtil.uploadFile(ossClient, ossConfigure.getBucketName(),
                    new FileInputStream(file), file.getName());

            uploadService.deteleTempFile();
            vo.setFileName(filename);
            vo.setFileSize(Long.parseLong(base64Code.length() + ""));
//            vo.setFileUploadName();
            return vo;
        } catch (ServiceException se) {
            vo.setErrorCode(se.getErrorCode());
            vo.setErrorDesc(se.getMessage());
        } catch (Exception e) {
            logger.info(e.getMessage());
            vo.setErrorDesc(ErrorCodeEnum.otherError.getErrorMsg());
            vo.setErrorCode(ErrorCodeEnum.otherError.getErrorCode());
        } finally {
            OSSManageUtil.closeOSSClient(ossClient);
        }
        return vo;
    }


    /**
     * oss文件上传
     *
     * @return filevo 包含错误日志
     */
    @Transactional
    public FileVo uploadFilesByte(byte[] buff) {

        FileVo vo = new FileVo();
        OSSClient ossClient = null;
        try {
            ossClient = OSSManageUtil.getOSSClient(ossConfigure);
            String fileName = UuidUtils.uuid() + ".png";
            OSSManageUtil.uploadFile(ossClient, ossConfigure.getBucketName(),
                    buff, fileName);

            uploadService.deteleTempFile();
            vo.setFileName(fileName);
            vo.setFileSize(Long.parseLong(buff.length + ""));

            return vo;
        } catch (ServiceException se) {
            vo.setErrorCode(se.getErrorCode());
            vo.setErrorDesc(se.getMessage());
        } catch (Exception e) {
            logger.info(e.getMessage());
            vo.setErrorDesc(ErrorCodeEnum.otherError.getErrorMsg());
            vo.setErrorCode(ErrorCodeEnum.otherError.getErrorCode());
        } finally {
            OSSManageUtil.closeOSSClient(ossClient);
        }
        return vo;
    }


    /**
     * oss 文件下载
     *
     * @param response 返回请求
     * @param fileName 文件名称
     */
    public void downloadFile(HttpServletResponse response, String fileName) {
        OSSClient ossClient = null;
        try {
            ossClient = OSSManageUtil.getOSSClient(ossConfigure);
            OSSObject ossObject = OSSManageUtil.downloadFile(ossClient, ossConfigure.getBucketName(), fileName);
            setHttpServletResponse(response, ossObject);
        } catch (Exception e) {
            logger.info(e.getMessage());
            throw new ServiceException(ErrorCodeEnum.otherError.getErrorMsg(), ErrorCodeEnum.otherError.getErrorCode());
        } finally {
            OSSManageUtil.closeOSSClient(ossClient);//关闭ossclient
        }
    }

    /**
     * oss 删除文件
     *
     * @param fileName
     * @return 删除成功返回 true 失败有异常抛出
     */
    public FileVo deleteFile(String fileName) {
        OSSClient ossClient = null;
        FileVo vo = new FileVo();
        try {
            ossClient = OSSManageUtil.getOSSClient(ossConfigure);
            OSSManageUtil.deleteFile(ossClient, ossConfigure.getBucketName(), fileName);
            return vo;
        } catch (Exception e) {
            logger.info(e.getMessage());
            vo.setErrorCode(ErrorCodeEnum.otherError.getErrorCode());
            vo.setErrorDesc(ErrorCodeEnum.otherError.getErrorMsg());
            return vo;
        } finally {
            OSSManageUtil.closeOSSClient(ossClient);
        }
    }

    /**
     * 判断是否为正确文件类型（JPG,GIF,PNG）是 true 否 false
     *
     * @return
     */
    private boolean isCorrectFileType(String filetype) {
        String[] filetypes = {"JPG", "GIF", "PNG"};
        for (String type : filetypes) {
            if (type.equals(filetype.toUpperCase())) {
                return true;
            }
        }
        return false;
    }

    /**
     * 设置返回响应信息
     *
     * @param response
     * @param ossObject
     * @throws IOException
     */
    private void setHttpServletResponse(HttpServletResponse response, OSSObject ossObject) throws IOException {
        response.setContentLengthLong(ossObject.getObjectMetadata().getContentLength());
        DateFormat df = new SimpleDateFormat(
                "EEE, dd MMM yyyy HH:mm:ss z", Locale.ENGLISH);
        Date uploadDate = ossObject.getObjectMetadata().getLastModified();
        String lastModified = df.format(uploadDate);
        response.setContentType("image/*");
        long maxAge = 60L * 60L;
        response.setHeader("Cache-Control", "max-age=" + maxAge);
        response.setHeader("Last-Modified", lastModified);
        response.setDateHeader("Expires", uploadDate.getTime() + maxAge
                * 1000L);
        //将inputstream写入response
        byte[] buffer = new byte[1024];
        int len = 0;
        while ((len = ossObject.getObjectContent().read(buffer)) > 0) {
            response.getOutputStream().write(buffer, 0, len);
        }
    }

    /**
     * 验证文件类型
     *
     * @param fileInputStream 文件流
     */
    private void verifyFileType(InputStream fileInputStream) {
        try {
            String sourceType = FileTypeJudge.getType(fileInputStream).toString();
            if (!CommonTools.limitFileType(sourceType, cfg.getPermitType())) {
                throw CommonTools.createException(ErrorCodeEnum.imageTypeError);
            }
        } catch (Exception e) {
            throw CommonTools.createException(ErrorCodeEnum.imageTypeError);
        }
    }

    /**
     * 验证文件大小
     *
     * @param fileSize 文件大小
     */
    private void verifyFileSize(Long fileSize) {
        if (fileSize > cfg.getPermitSize()) {
            throw CommonTools.createException(ErrorCodeEnum.imageTooLarge);
        }
    }


    @Transactional
    public FileVo videoUploadFiles(MultipartFile file) {
        FileVo vo = new FileVo();
        OSSClient ossClient = null;
        try {
            String suffix = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf("."));
            //验证视频文件类型
            verifyVideoFileType(file.getInputStream(),suffix.substring(1));
            //验证视频文件大小
            verifyVideoFileSize(file.getSize());

            ossClient = OSSManageUtil.getOSSClient(ossConfigure);
            String filename = OSSManageUtil.uploadFile(ossClient, ossConfigure.getBucketName(), file);

            vo.setFileName(filename);
            vo.setFileSize(file.getSize());
            vo.setFileUploadName(file.getOriginalFilename());
            return vo;
        } catch (ServiceException se) {
            vo.setErrorCode(se.getErrorCode());
            vo.setErrorDesc(se.getMessage());
        } catch (Exception e) {
            logger.info(e.getMessage());
            vo.setErrorDesc(ErrorCodeEnum.otherError.getErrorMsg());
            vo.setErrorCode(ErrorCodeEnum.otherError.getErrorCode());
        } finally {
            OSSManageUtil.closeOSSClient(ossClient);
        }
        return vo;
    }

    /**
     * @Author gaoqiang
     * @Description 验证视频文件类型
     * @param fileInputStream
     * @return
     * @Date 2018/7/28 19:11
     */
    private void verifyVideoFileType(InputStream fileInputStream,String type) {
        try {
            //String sourceType = FileTypeJudge.getVideoType(fileInputStream).toString();
            String sourceType = type;
            if (!CommonTools.limitFileType(sourceType, cfg.getVideoPermitType())) {
                throw CommonTools.createException(ErrorCodeEnum.videoTypeError);
            }
        } catch (Exception e) {
            throw CommonTools.createException(ErrorCodeEnum.videoTypeError);
        }
    }

    /**
     * @Author gaoqiang
     * @Description  验证视频文件大小
     * @param fileSize
     * @return
     * @Date 2018/7/28 19:26
     */
    private void verifyVideoFileSize(Long fileSize) {
        if (fileSize > cfg.getVideoPermitSize()) {
            throw CommonTools.createException(ErrorCodeEnum.videoTooLarge);
        }
    }


}
